﻿using DDLParser.constant;
using DDLParser.main;
using DDLParser.model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DDLParser
{
    public class DDLIterator : IDDLIterator
    {
        //private StreamReader stream;
        protected int LineNumber { get; set; }
        protected int LineOffset { get; set; }
        protected int TextOffset { get; set; }
        protected DDLWord PrivousWord { get; set; }
        protected string TextBlock { get; set; }
        protected int TextLength { get; set; }
        protected int BeginWordOffset { get; set; }
        protected int WordLineNumber { get; set; }
        protected int WordLineOffset { get; set; }
        protected int WordLength { get; set; }
        public DDLTerminatorLookup OneCharTerminator { get; set; }

        //protected List<DDLTerm> OneCharTerminator { get; set; } // terminator for one char

        public DDLIterator(StreamReader stream)
        {
            //this.stream = stream;
            LineNumber = 1;
            LineOffset = 1;
            TextOffset = 0;
            TextBlock = stream.ReadToEnd();
            TextLength = TextBlock.Length;
            BeginWordOffset = 0;
            WordLineNumber = 0;
            WordLineOffset = 1;
            WordLength = 0;

            OneCharTerminator = new DDLTerminatorLookup();
        }

        public bool HasNext()
        {
            bool result = (TextOffset >= TextLength) ? false : true;

            return result;
        }

        public DDLWord Next()
        {
            DDLWord result = new DDLWord();

            //IComparer<DDLTerm> comparator = new TermComparator();
            BeginWordOffset = TextOffset;
            WordLineNumber = LineNumber;
            WordLineOffset = LineOffset;
            WordLength = 0;
            int terminatorType = DDLTermType.UNKNOWN;
            while (TextOffset < TextLength)
            {
                string dataStr = TextBlock.Substring(TextOffset, 1);
                DDLWord searchWord = new DDLWord();
                searchWord.Word = dataStr;
                terminatorType = OneCharTerminator.GetType(searchWord);
                if (terminatorType != DDLTermType.UNKNOWN)
                {
                    WordLength = TextOffset - BeginWordOffset;

                    if (terminatorType == DDLTerminatorType.SPACE ||
                        terminatorType == DDLTerminatorType.TAB)
                    {
                        if (DoSpaceTerminator(terminatorType))
                        {
                            break;
                        }
                    }
                    else if (terminatorType == DDLTerminatorType.RETURN)
                    {
                        if (DoReturnTerminator(terminatorType))
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (DoTerminatorTerm(terminatorType))
                        {
                            break;
                        }
                    }
                }

                TextOffset++;
                LineOffset++;
            }

            string resultWord = "";
            if (WordLength > 0)
            {
                resultWord = TextBlock.Substring(BeginWordOffset,WordLength);
            }

            result.Word = resultWord;
            result.LineOffset = WordLineOffset;
            result.LineNumber = WordLineNumber;
            result.TerminatorType = terminatorType;

            return result;
        }

        protected bool DoSpaceTerminator(int terminatorType)
        {
            bool isBreak = false;
            if (WordLength > 0)
            {
                TextOffset++;
                LineOffset++;
                isBreak = true;
            }
            else
            {
                BeginWordOffset = TextOffset + 1;
            }

            return isBreak;
        }

        protected bool DoReturnTerminator(int terminatorType)
        {
            bool isBreak = true;

            string previousStr = TextBlock.Substring(TextOffset - 1, 1);
            if (previousStr == "\r")
            {
                WordLength--;
            }

            if (WordLength > 0)
            {
                TextOffset--;
            }
            else
            {
                LineNumber++;
                LineOffset = 1;
                TextOffset++;
                WordLength = 2;
            }

            return isBreak;
        }

        protected virtual bool DoTerminatorTerm(int terminatorType)
        {
            bool isBreak = false;

            return isBreak;
        }
    }
}
